/*jslint vars: true, forin: true, sloppy: true */
/*global angular, DialogFactory, debug, DM, defaults, ocDialog, $DF */
ocDialog.provider('ocDialog', function () {
	// Getter/Setter for defaults.
	var config = this.config = function (item, value) {
		if (!defaults.hasOwnProperty(item)) {
			throw new Error(debug["#1101"]);
		}

		if (angular.isDefined(value)) {
			defaults[item] = value;
		}
		return defaults[item];
	};

	this.$get = function ($q, $http, $rootScope, $compile, $templateCache) {

		$DF.getDialogInstance = function (data) {
			// It makes the application layout can not compile "oc-dialog"
			// directive directly by this way.
			var newScope = $rootScope.$new();
			newScope.data = data;
			angular.extend(newScope);
			return $compile(this.$dialogRaw)(newScope).data('dialogInstance');
		};

		var exports = {
			getDialogInstanceByDialogFactoryName: function (opt) {
				/**
				 * opt.name
				 * opt.data
				 */
				var deffered = $q.defer();

				// DF (D)ialog (F)actory.
				if (DM.factoryList[opt.name]) {
					deffered.resolve(DM.factoryList[opt.name]
						.getDialogInstance(opt.data));
				} else {
					var url = defaults.ROUTE_PATH + defaults.ROUTE_PREFIX +
						opt.name + defaults.ROUTE_SUFFIX;

					$http.get(url, {
						cache: $templateCache
					}).success(function (raw) {
						deffered.resolve((new DialogFactory(opt.name, raw))
                            .getDialogInstance(opt.data));
					}).error(function () {
						deffered.reject('Can NOT found by url: ' + url + '.');
					});
				}

				// Give a Dialog Element to callback function.
				return deffered.promise;
			},
			queryDialogByElement: DM.queryDialogByElement,
			open: function (setup, parentDI) {
				this.getNewDI(setup).then(function (DI) {
					DI.openDialogFrom(parentDI);
				});
			},
			alert: function (setup, parentDI) {
				/**
				 * setup.title
				 * setup.message
				 * setup.okFn
				 * setup.cancelFn
				 */
				this.getNewDI({name: 'oc-alert'}).then(function (DI) {
					var s = DI.$$scope;

					s.title = setup.title;
					s.message = setup.message;
					s.closeButtonFn = function () {
						(setup.cancelFn || angular.noop)(DI);
					};
					s.okFn = function () {
						(setup.okFn || angular.noop)(DI);
					};

					DI.openDialogFrom(parentDI);
				});
			},
			file: function (setup, parentDI) {
				/**
				 * setup.actionName
				 * setup.actionFn
				 * setup.title
				 * setup.data
				 * setup.init
				 * setup.toolbar
				 * setup.mapName
				 * setup.mapUpdatetime
				 */
				var share = (setup.share || angular.noop)();
				delete setup.share;

				this.getNewDI({name: 'oc-file'}).then(function (DI) {
					angular.extend(DI.$$scope, setup);
					(setup.init || angular.noop)(DI.$$scope, DI);
					DI.openDialogFrom(parentDI);
				});
			}
		};

		// Alias.
		exports.getNewDI = exports.getDialogInstanceByDialogFactoryName;
		exports.queryDI = exports.queryDialogByElement;

		return exports;
	};
});
